import * as THREE from '../../build/three.module.js';
import Stats from '../../jsm/libs/stats.module.js';

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(65, innerWidth / innerHeight, 1, 10000);
camera.position.z = 300;

const gmt = new THREE.BufferGeometry(),
      radius = 200,
      positions = [],
      colors = [],
      sizes = [],
      color = new THREE.Color(),
      particles = 10000;

const uniforms = {
  pointTexture: {
    value: new THREE.TextureLoader().load('../../textures/sprite/spark1.png')
  }
};  

const mtl = new THREE.ShaderMaterial({
  uniforms: uniforms,
  vertexShader: document.getElementById('vertexShader').textContent,
  fragmentShader: document.getElementById('fragmentShader').textContent,
  
  blending: THREE.AdditiveBlending,
  depthTest: false,
  transparent: true,
  vertexColors: true
});

for(let i = 0; i < particles; i += 1) {
  positions.push(Math.sin(Math.random() * 2 - 1) * radius); // 定位在 -200 到 200 的立方空间内
  positions.push(Math.sin(Math.random() * 2 - 1) * radius);
  positions.push(Math.sin(Math.random() * 2 - 1) * radius);

  color.setHSL(i / particles, 1, .5);

  colors.push(color.r, color.g, color.b);

  sizes.push(20)
}

gmt.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
gmt.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
gmt.setAttribute( 'size', new THREE.Float32BufferAttribute( sizes, 1 ).setUsage( THREE.DynamicDrawUsage ) );

const particleSystem = new THREE.Points(gmt, mtl);

scene.add(particleSystem);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

const stats = new Stats();
document.body.appendChild(stats.dom);

const render = () => {
  const time = Date.now() * .005;
  particleSystem.rotation.z = .01 * time;
  const sizes = gmt.attributes.size.array;

  for(let i = 0; i < particles; i += 1) {
    sizes[i] = 10 * (1 + Math.sin(.1 * i + time));
  }

  gmt.attributes.size.needsUpdate = true;
  
  renderer.render(scene, camera);
}

const animate = () => {
  requestAnimationFrame(animate);

  render();
  stats.update();
}
animate();

const handleWindowResize = () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);
}
window.addEventListener('resize', handleWindowResize, false);